﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Net.Sockets;
using System.Net;
using System.IO;

namespace senSimulator.NetworkComponents
{
    class NetworkController
    {
        private Controller _controller;
        private NetworkReader _networkReader;
        private Thread _networkReaderThread;
        private NetworkWriter _networkWriter;
        private Thread _networkWriterThread;        
        private int _portNumber;
        private String _ipAdress;
        private TcpClient _client;
        private bool _networkMode;

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="portNumber">set portnumber for communication</param>
        /// <param name="ipAdress">set ipadres for communication</param>
        /// <param name="controller">gives the controller to the NetworkController</param>
        public NetworkController(int portNumber, string ipAdress, Controller controller, bool networkMode)
        {
            this._controller = controller;
            this._portNumber = portNumber;
            this._ipAdress = ipAdress;
            this._networkMode = networkMode;
        }


        /// <summary>
        /// Initialize networkcommunication
        /// </summary>
        /// <returns>success</returns>
        public void InitializeNetwork()
        {
            while (!_controller.Initialized())
            {
                Thread.Yield();
            }
            _client = new TcpClient();

            while (!_client.Connected)
            {
                try
                {
                    _client.Connect(_ipAdress, _portNumber);
                    Console.WriteLine(_client.Connected);

                    initializeWriterReader(_client);

                }
                catch (Exception e)
                {
                    Console.WriteLine("Connection not possible because: " + e.Message);
                    Console.WriteLine("Trying again...\n");
                    Thread.Yield();
                }
            }
        }


        private void initializeWriterReader(TcpClient client)
        {
            Console.WriteLine("Connected to server Controller");

            NetworkStream stream = client.GetStream();

            _networkReader = new NetworkReader(stream, this, _networkMode);
            _networkReaderThread = _networkReader.Prepare();
            _networkReaderThread.Start();

            _networkWriter = new NetworkWriter(stream, this, _networkMode);
            _networkWriterThread = _networkWriter.Prepare();
            _networkWriterThread.Start();
        }


        /// <summary>
        /// Sends sensor information to the controller
        /// </summary>
        /// <param name="trafficLightID">ID of the traffic light</param>
        /// <param name="distanceToTrafficLight">distance of the sensor to the traffic light</param>
        public void sendSensorInfo(string trafficLightID, int distanceToTrafficLight, string direction)
        {
            commandData cmd = new commandData();
            cmd.command = 0;
            cmd.parameters = trafficLightID + "," + distanceToTrafficLight + "," + direction;
            _networkWriter.SetCommand(cmd);
        }


        /// <summary>
        /// Procces the incomming commands and decides what to do with it
        /// </summary>
        /// <param name="command">Command code</param>
        /// <param name="parameter">a string</param>
        public void ProcessIncommingCommand(int command, string parameter)
        {
            string[] p = parameter.Split(',');
            switch (command)
            {   
                //Add traffic to the simulator             
                case 0:
                    _controller.AddTrafficToTrafficLightLane(p[0], p[1], p[2]);
                    break;
                case 1:
                    _controller.ChangeTrafficLightState(p[0], Convert.ToInt16(p[1]));
                    break;
                default:
                    Console.WriteLine("Invalid command {0} with parameter(s): {1}", command, parameter);
                    break;
            }
        }


        public TcpClient GetClient()
        {
            return _client;
        }
    }
}